package com.naiterui.ehp.bp.security.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import com.naiterui.common.redis.RedisUtil;
import com.naiterui.ehp.bp.security.properties.SecurityProperties;
import com.naiterui.ehp.bp.security.service.IOnlineUserService;
import com.naiterui.ehp.bp.security.utils.BaseJwtUser;
import com.naiterui.ehp.bp.security.utils.EncryptUtils;
import com.naiterui.ehp.bp.security.utils.RequestHolder;
import com.naiterui.ehp.bp.security.vo.OnlineUserVO;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

@Service
@Slf4j
@AllArgsConstructor
public class OnlineUserServiceImpl implements IOnlineUserService {

  private final SecurityProperties properties;

  @Override
  public void save(BaseJwtUser baseJwtUser, String token) {
    String userAgentString = RequestHolder.getHttpServletRequest().getHeader("user-agent");
    UserAgent userAgent = UserAgentUtil.parse(userAgentString);
    OnlineUserVO onlineUserVO = OnlineUserVO.builder()
        .id(baseJwtUser.getId())
        .userName(baseJwtUser.getUsername())
        .key(EncryptUtils.desEncrypt(token))
        .ip(ServletUtil.getClientIP(RequestHolder.getHttpServletRequest()))
        .browser(userAgent.getBrowser().getName())
        .loginTime(new Date())
        .build();
    RedisUtil.valueOps().setObject(this.properties.getOnlineKey() + token, onlineUserVO, this.properties.getTokenValidityInSeconds());
  }

  /**
   * 查询全部数据，不分页
   *
   * @param filter /
   * @return /
   */
  @Override
  public List<OnlineUserVO> getAll(String filter) {
    List<String> keys = RedisUtil.keyOps().scan(this.properties.getOnlineKey() + "*");
    Collections.reverse(keys);
    List<OnlineUserVO> onlineUserVOS = new ArrayList<>();
    keys.stream().map(key -> (OnlineUserVO) RedisUtil.valueOps().getObject(key)).forEachOrdered(onlineUserVO -> {
      if (StringUtils.isNotBlank(filter)) {
        if (onlineUserVO.getUserName().equalsIgnoreCase(filter)) {
          onlineUserVOS.add(onlineUserVO);
        }
      } else {
        onlineUserVOS.add(onlineUserVO);
      }
    });
    onlineUserVOS.sort((o1, o2) -> o2.getLoginTime().compareTo(o1.getLoginTime()));
    return onlineUserVOS;
  }

  /**
   * 踢出用户
   *
   * @param key /
   */
  @Override
  public void kickOut(String key) {
    key = this.properties.getOnlineKey() + key;
    RedisUtil.keyOps().delete(key);
  }

  /**
   * 退出登录
   *
   * @param token /
   */
  @Override
  public void logout(String token) {
    String key = this.properties.getOnlineKey() + token;
    RedisUtil.keyOps().delete(key);
  }

  /**
   * 查询用户
   *
   * @param key /
   * @return /
   */
  @Override
  public OnlineUserVO getOne(String key) {
    return (OnlineUserVO) RedisUtil.valueOps().getObject(key);
  }

  /**
   * 检测用户是否在之前已经登录，已经登录踢下线
   *
   * @param userName 用户名
   */
  @Override
  public void checkLoginOnUser(String userName, String igoreToken) {
    List<OnlineUserVO> onlineUserVOS = this.getAll(userName);
    if (CollectionUtil.isEmpty(onlineUserVOS)) {
      return;
    }
    for (OnlineUserVO onlineUserVO : onlineUserVOS) {
      if (onlineUserVO.getUserName().equals(userName)) {
        try {
          String token = EncryptUtils.desDecrypt(onlineUserVO.getKey());
          if (StringUtils.isNotBlank(igoreToken) && !igoreToken.equals(token)) {
            this.kickOut(token);
          } else if (StringUtils.isBlank(igoreToken)) {
            this.kickOut(token);
          }
        } catch (Exception e) {
          log.error("checkUser is error", e);
        }
      }
    }
  }

}
